package com.fangcang.mongodb.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.bson.conversions.Bson;

import com.mongodb.client.model.Aggregates;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Sorts;
import com.mongodb.client.model.Updates;

/**
 * mongodb查询条件封装类
 * @author fangcang
 * @date 2019年3月1日
 * @description
 */
public class MongoBuilder {
	
	private List<Bson> filters = new ArrayList<Bson>();
	
	private MongoBuilder() {
		
	}
	
	public static MongoBuilder builder() {
		return new MongoBuilder();
	}
	
	public  MongoBuilder eq(String fieldName, String value) {
		filters.add(Filters.eq(fieldName, value));
		return this;
	}
	
	
	public  MongoBuilder elmeMatch(String fieldName, Bson filter) {
		filters.add(Filters.elemMatch(fieldName, filter));
		return this;
	}

	/**
	 * and 查询条件 a=1 and b=2
	 * @param list
	 * @return
	 */
	public  MongoBuilder and(List<Bson> list) {
		filters.add(Aggregates.match(Filters.and(list)));
		return this;
	}
	
	/**
	 *  and查询条件  a=1 and b=2
	 * @param map
	 * @return
	 */
	public  MongoBuilder and(Map<String, Object> map) {
		if(map == null || map.isEmpty()) {
			return this;
		}
		
		Set<Entry<String, Object>> sets = map.entrySet();
		List<Bson> andList = new ArrayList<Bson>(map.size());
		for (Entry<String, Object> set : sets) {
			andList.add(Filters.eq(set.getKey(), set.getValue()));
		}
		return and(andList);
	}
	
	/**
	 * or查询条件
	 * @param list
	 * @return
	 */
	public  MongoBuilder or(List<Bson> list) {
		filters.add(Aggregates.match(Filters.or(list)));
		return this;
	}
	
	/**
	 * or查询条件  a=1 or b=2
	 * @param map
	 * @return
	 */
	public  MongoBuilder or(Map<String, Object> map) {
		if(map == null || map.isEmpty()) {
			return this;
		}
		
		Set<Entry<String, Object>> sets = map.entrySet();
		List<Bson> orList = new ArrayList<Bson>(map.size());
		for (Entry<String, Object> set : sets) {
			orList.add(Filters.eq(set.getKey(), set.getValue()));
		}
		return or(orList);
	}
	
	/**
	 * in查询条件  a in (1, 2)
	 * @param fieldName
	 * @param values
	 * @return
	 */
	public  MongoBuilder in(String fieldName, Object... values) {
		filters.add(Aggregates.match(Filters.in(fieldName, values)));
		return this;
	}
	
	/**
	 * 升序排序字段 order by a ase
	 * @param fieldNames
	 * @return
	 */
	public  MongoBuilder aseSort(String... fieldNames) {
		filters.add(Aggregates.sort(Sorts.ascending(fieldNames)));
		return this;
	}
	
	/**
	 * 降序排序 order by a desc
	 * @param fieldNames
	 * @return
	 */
	public  MongoBuilder descSort(String... fieldNames) {
		filters.add(Aggregates.sort(Sorts.descending(fieldNames)));
		return this;
	}
	
	/**
	 * 跳过记录数，用于分页
	 * @param skip
	 * @return
	 */
	public  MongoBuilder skip(int skip) {
		filters.add(Aggregates.skip(skip));
		return this;
	}
	
	
	/**
	 * 查询记录条件，limit 10
	 * @param limit
	 * @return
	 */
	public  MongoBuilder limit(int limit) {
		filters.add(Aggregates.limit(limit));
		return this;
	}
	
	/**
	 * 小于查询条件  a<10
	 * @param fieldName
	 * @param value
	 * @return
	 */
	public  MongoBuilder lt(String fieldName, Object value) {
		filters.add(Aggregates.match(Filters.lt(fieldName, value)));
		return this;
	}
	
	/**
	 *  小于等于查询条件  a<=10
	 * @param fieldName
	 * @param value
	 * @return
	 */
	public  MongoBuilder lte(String fieldName, Object value) {
		filters.add(Aggregates.match(Filters.lte(fieldName, value)));
		return this;
	}
	
	/**
	 * 大于等于查询条件 a>=10
	 * @param fieldName
	 * @param value
	 * @return
	 */
	public  MongoBuilder gte(String fieldName, Object value) {
		filters.add(Aggregates.match(Filters.gte(fieldName, value)));
		return this;
	}
	
	/**
	 * 大于查询条件 a>10
	 * @param fieldName
	 * @param value
	 * @return
	 */
	public  MongoBuilder gt(String fieldName, Object value) {
		filters.add(Aggregates.match(Filters.gt(fieldName, value)));
		return this;
	}
	
	public  MongoBuilder combine(String fieldName, Object value) {
		filters.add(Updates.combine(Updates.set(fieldName, value)));
		return this;
	}
	
	public  MongoBuilder set(String fieldName, Object value) {
		filters.add(Updates.set(fieldName, value));
		return this;
	}
	

	public List<Bson> getFilters() {
		return filters;
	}

	public void setFilters(List<Bson> filters) {
		this.filters = filters;
	}
}
